package cz.cuni.amis.episodic.bayes.experiment;

import java.io.File;
import static cz.cuni.amis.episodic.bayes.utils.MultiexperimentSummary.*;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import org.apache.commons.math.stat.ranking.NaturalRanking;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.YIntervalSeries;
import org.jfree.data.xy.YIntervalSeriesCollection;

import com.beust.jcommander.converters.IntegerConverter;

import cz.cuni.amis.episodic.bayes.memories.IntervalSurpriseMemoryCreator;
import cz.cuni.amis.episodic.bayes.memories.MemoryCreator;
import cz.cuni.amis.episodic.bayes.memories.MinimizeKLMemoryCreator;
import cz.cuni.amis.episodic.bayes.utils.DeviationGraph;
import cz.cuni.amis.episodic.bayes.utils.chart.AgregateGraphDevice;
import cz.cuni.amis.episodic.bayes.utils.chart.GraphPaintingDevice;
import cz.cuni.amis.episodic.bayes.utils.chart.PdfGraphDevice;
import cz.cuni.amis.episodic.bayes.utils.chart.PngGraphDevice;
import cz.cuni.amis.episodic.lisp.netcreators.AHMEMCreator;
import cz.cuni.amis.episodic.lisp.netcreators.CHMMCreator;
import cz.cuni.amis.episodic.lisp.netcreators.TraceModificationStrategy;
import cz.cuni.amis.episodic.lisp.netcreators.UpperTraceAndObservationStrategy;

/**
 * ICCM 2013 experiment.
 * 
 * @author ik
 */
public class Experiment_4c_monroe_effectOfTrainingData extends LispExperiment {

	public static String expsRootFolder = "target/experiments/4_monroe_effectOfTrainingData";
	
	@Override
	protected GraphPaintingDevice createGraphDevice(File rootDir) {
		return new AgregateGraphDevice(new GraphPaintingDevice[] {
				new PdfGraphDevice(rootDir), new PngGraphDevice(rootDir) },
				rootDir);
	}

	protected MemoryCreator[] createMemoryCreators(GraphPaintingDevice device) {
		return new MemoryCreator[] { new IntervalSurpriseMemoryCreator(device),
				new MinimizeKLMemoryCreator(device) };
	}

	public Experiment_4c_monroe_effectOfTrainingData(String expName, String rootFolder, String dataset) {
		super(expName, new File(
				rootFolder), new File(
				dataset));

		networkFilenames = new String[] {};
		batchSize = 10;
		createAndLearnNetworks = true;
		drawMemoryCreationGraphs = false;
		performEvolutionExample = false;

		TraceModificationStrategy level1 = new UpperTraceAndObservationStrategy(
				1);
		TraceModificationStrategy level2 = new UpperTraceAndObservationStrategy(
				2);

		networkCreators = Arrays.asList(new CHMMCreator(true, level1),
				new AHMEMCreator(8, level1, true)
		// new CHMMCreator(true, level2)
				/*
				 * new AHMEMCreator(2, level1, true), new AHMEMCreator(2,
				 * level2, true), new AHMEMCreator(4, level1, true), new
				 * AHMEMCreator(4, level2, true), new AHMEMCreator(8, level1,
				 * true), new AHMEMCreator(8, level2, true)
				 */
				);

	}

	public static void createTrainingDataInfluenceGraph(String expsRootFolder) throws Exception {

		List<Entry<Integer, Map<String, Map<String, DescriptiveStatistics[][]>>>> list = loadMultiExperimentResultData(expsRootFolder);

		// create dataset for graph
		YIntervalSeriesCollection dataset1 = createGraphDataset(list, 
				new String[] {"monroe-small_chmm-obs^1", "monroe-small_ahmem-obs^1_8"},
				new String[] {"retro_ig"},
				new int[] {0},
				new int[] {2}); 
		
		YIntervalSeriesCollection dataset2 = createGraphDataset(list, 
				new String[] {"monroe-small_chmm-obs^1", "monroe-small_ahmem-obs^1_8"},
				new String[] {"retro_interval"},
				new int[] {0},
				new int[] {2}); 
		
		
		showTrainingDataInfluenceGraph(dataset1);
		showTrainingDataInfluenceGraph(dataset2);
	}

	public static void main(String[] args) throws Exception {
		int numberOfDaysInOneBatch = 30;

		int testingData = numberOfDaysInOneBatch;
		
		createTrainingDataInfluenceGraph(expsRootFolder);

		for (int i = 1; i < 5; i++) {
			int trainingDataNum = i * numberOfDaysInOneBatch;

			Experiment e = new Experiment_4c_monroe_effectOfTrainingData(
					"unseen_split-" + trainingDataNum, expsRootFolder, "../datasets/4_monroe/monroe-small.txt");
			// Experiment e = new
			// Experiment_4c_monroe_effectOfTrainingData("4_monroe_smoothed_split"+trainingDataNum);
			e.setTestingDataRange(new int[] { 0, testingData });
			e.setTrainingDataRange(new int[] { testingData,
					testingData + trainingDataNum });
			// e.setTrainingDataRange(new int[] {0, trainingDataNum});
			e.perform();
		}
	}
}
